/*
 * @Author: czy
 * @Date: 2021-04-04 22:39:40
 * @LastEditTime: 2021-05-21 22:42:03
 */
#include "const.h"
#include "libio.h"
#include "stdarg.h"
#include "string.h"
#include "vsprintf.h"

#include "api/system.h"

#define BUFSIZE 400

FILE _uart = {UART};
FILE _vga = {VGA};
FILE _vga_uart = {VGA_UART};
FILE *stdin = &_uart;
FILE *stdout = &_vga_uart;
FILE *stderr = &_vga;
FILE *vga = &_vga;
FILE *uart = &_uart;

static char BUFFER[BUFSIZE];

/**
 * @description: Formats a string in the specified format, and output to output device.
 * @param stream    Output stream.
 * @param format    Format string.
 * @param args      Parameter list.
 * @return The length of the string in the buffer.
 */
int vfprintf(FILE *stream, const char *format, va_list args)
{
    int n;
    strzero(BUFFER, BUFSIZE);
    n = vsprintf(BUFFER, format, args);
    write(BUFFER, stream->stream);
    return n;
}

/**
 * @description: Formats a string in the specified format, and output to output device.
 * @param stream    Output stream.
 * @param format    Format string.
 * @return The length of the string in the buffer.
 */
int fprintf(FILE *stream, const char *format, ...)
{
    int n;
    va_list args;
    va_start(args, format);
    n = vfprintf(stream, format, args);
    va_end(args);
    return n;
}

/**
 * @description: Formats a string in the specified format, and output to standard output device.
 * @param format    Format string.
 * @param args      Parameter list.
 * @return The length of the string in the buffer.
 */
int vprintf(const char *format, va_list args)
{
    return vfprintf(stdout, format, args);
}

/**
 * @description: Formats a string in the specified format, and output to standard output device.
 * @param format    Format string.
 * @return The length of the string in the buffer.
 */
int printf(const char *format, ...)
{
    int n;
    va_list args;
    va_start(args, format);
    n = vprintf(format, args);
    va_end(args);
    return n;
}

/**
 * @description: Get a character from input device.
 * @param stream    Input stream.
 * @return Character.
 */
int fgetc(FILE *stream)
{
    getc(stream->stream);
}

/**
 * @description: Output a character to output device.
 * @param ch    Character to be output.
 * @param stream    Output stream.
 * @return Character.
 */
int fputc(int ch, FILE *stream)
{
    putc(ch, stream->stream);
    return ch;
}

/**
 * @description: Get a character from standard input device.
 * @return Character.
 */
int getchar(void)
{
    return fgetc(stdin);
}

/**
 * @description: Output a character to standard output device.
 * @param ch    Character to be output.
 * @return Character.
 */
int putchar(int ch)
{
    return fputc(ch, stdout);
}

/**
 * @description: Clear standard output device.
 */
void clear(void)
{
    cls(stdout->stream);
}

/**
 * @description: Outputs message at a specified location, such as the current time. 
 *                  When the output is finished, the cursor returns to its original position.
 * @param position  LEFT if 1 else RIGHT.
 * @param color     Output color.
 * @param format    Format.
 */
void message(int position, const char *color, char *format, ...)
{
    char str1[100] = "", str2[100] = "";
    va_list args;
    va_start(args, format);
    vsprintf(str1, format, args);
    sprintf(str2, "%s%s\033[0m", color, str1);
    gotoxy(position == 1 ? 0 : 80 - strlen(str1), 24, str2, stdout->stream);
}
